package com.suray.rgv60.task;

import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.utils.LoggerType;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.rgv.util.RgvLogger;
import com.suray.rgv60.exception.ExecTaskException;
import com.suray.rgv60.util.RgvTaskType;
import com.suray.type.Rgv60TaskStatus;

import java.util.ArrayList;
import java.util.List;

/**
 * 任务信息
 */
public class TaskInfo {
    /**
     * 主任务id
     */
    private Object taskId;

    /**
     * 任务所需行驶的点位（可空）
     * 如果为空则无效
     * 如果不为空，则判断任务完成是需校验该坐标
     */
    private List<Node> path;

    /**
     * 小车任务
     */
    private List<RgvTaskInfo> rgvTasks;

    /**
     * 前面任务的最后一个节点，用来接续任务
     */
    private Node lastNode;

    /**
     * 任务下发指针
     */
    private int taskPtr;

    /**
     * 任务车辆序列号
     */
    private String serialNum;

    /**
     * 任务类型
     */
    private RgvTaskType taskType;

    private String endPoint;

    public TaskInfo(Object taskId, List<Node> nodes, String serialNum, RgvTaskType taskType) {
        this.taskId = taskId;
        this.serialNum = serialNum;
        this.taskPtr = 0;

        rgvTasks = new ArrayList<>();

        if (taskType == RgvTaskType.RGV_60_TASK) {
            if (nodes.size() < 2) {
                throw new RuntimeException("节点个数不够，无法生成小车任务:" + WcsFuncUtil.listToString(nodes));
            }
            addTask(nodes, taskType);
        }

        this.taskType = taskType;
    }

    public TaskInfo(Object taskId, Node lastNode, List<Node> path, String serialNum, RgvTaskType taskType) {
        this.taskId = taskId;
        this.serialNum = serialNum;
        this.taskPtr = 0;

        rgvTasks = new ArrayList<>();

        this.lastNode = lastNode;
        this.path = path;
        this.endPoint = path.get(path.size() - 1).getRgv60Point();
        checkPath(lastNode);

        this.taskType = taskType;
    }

    /**
     * 仅用于查找临时任务
     * @param taskNo
     * @param startNode
     * @param endNode
     * @param serialNum
     */
    public TaskInfo(String taskNo, Node startNode, Node endNode, String serialNum, RgvTaskType taskType) {
        this.serialNum = serialNum;
        rgvTasks = new ArrayList<>();
        rgvTasks.add(new RgvTaskInfo(taskNo, startNode, endNode, serialNum, taskType));
    }

    public Object getTaskId() {
        return taskId;
    }

    public boolean checkTaskId(Object taskId) {
        return this.taskId.equals(taskId);
    }

    public void freshTaskStatus(String rgvTaskId, int status) {
        Rgv60TaskStatus taskStatus = Rgv60TaskStatus.parseStatus(status);

        for (RgvTaskInfo rgvTask : rgvTasks) {
            if (rgvTask.getTaskStatus() == Rgv60TaskStatus.COMPLETED) {
                for (int i = 0; i < rgvTasks.indexOf(rgvTask); i++) {
                    RgvTaskInfo task = rgvTasks.get(i);
                    if (task.getTaskStatus() != Rgv60TaskStatus.COMPLETED) {
                        task.setTaskStatus(Rgv60TaskStatus.COMPLETED);
                    }
                }
            }

            if (rgvTask.getRgvTaskNo().equals(rgvTaskId)) {
                rgvTask.setTaskStatus(taskStatus);
                break;
            }
        }
    }

    /**
     * 获取已经下发的任务id
     * @return
     */
    public List<String> getStartTasks() {
        List<String> tasks = new ArrayList<>();
        for (int i = 0; i < taskPtr; i++) {
            tasks.add(rgvTasks.get(i).getRgvTaskNo());
        }
        return tasks;
    }

    /**
     * 获取下一个执行的任务
     * @return
     */
    public RgvTaskInfo getNextTask() {
        if (taskPtr >= rgvTasks.size()) {
            return null;
        }

        return rgvTasks.get(taskPtr++);
    }

    /**
     * 生成任务
     * @param nodes
     */
    public void generalTasks(List<Node> nodes, RgvTaskType taskType) {
        List<Node> nodeList = new ArrayList<>();
        nodeList.add(lastNode);
        nodeList.addAll(nodes);
        addTask(nodeList, taskType);
    }

    /**
     * 添加任务
     * @param nodes
     * @param taskType
     */
    private void addTask(List<Node> nodes, RgvTaskType taskType) {
        Node tempNode = null;
        for (Node node : nodes) {
            if (tempNode == null) {
//                checkPath(node);
                tempNode = node;
                continue;
            }

            checkPath(node);
            RgvTaskInfo task = new RgvTaskInfo(tempNode, node, serialNum, taskType);
            rgvTasks.add(task);
            tempNode = node;
            RgvLogger.info(LoggerType.TASK, taskId, serialNum, "添加任务:" + task, this.getClass());
        }

        lastNode = WcsFuncUtil.getLastObj(nodes);
    }

    private void checkPath(Node node) {
        if (!path.get(0).equals(node)) {
            throw new RuntimeException("路径点错误：" + WcsFuncUtil.listToString(path) + ", 当前点：" + node);
        }
        path.remove(0);
    }

    public boolean checkTaskEnd(String currentStation) {
        for (RgvTaskInfo rgvTask : rgvTasks) {
            //TODO rgv6.0 异常状态处理
            if (rgvTask.getTaskStatus() == null || !rgvTask.getTaskStatus().equals(Rgv60TaskStatus.COMPLETED)) {
                return false;
            } else {
                switch (rgvTask.getTaskStatus()) {
                    case COMPLETED:
                        rgvTask.checkSameStatus();
                        break;
                    case RUNNING:
                    case WAITING:
                    case CANCELED:
                    case SUSPENDED:
                    case INVALID:
                        rgvTask.checkSameStatus();
                        return false;
                    case NOT_FOUND:
                        throw new ExecTaskException("查找不到任务", rgvTask.getRgvTaskNo());
                    case OVER_TIME:
                        throw new ExecTaskException("任务执行超时", rgvTask.getRgvTaskNo());
                    case FAILED:
                        throw new ExecTaskException("任务执行失败", rgvTask.getRgvTaskNo());
                    default:
                        throw new ExecTaskException("无效的任务状态:" + rgvTask.getTaskStatus(), rgvTask.getRgvTaskNo());
                }
            }
        }

        if (path != null && path.size() > 0) {
            //如果有路径，且路径不为空，则任务没完成
            return false;
        }

        if (!endPoint.equals(currentStation)) {
            //任务已经完成，等待小车坐标更新
            return false;
        }

        return true;
    }

    public boolean isAllTaskEnd() {
        for (RgvTaskInfo rgvTask : rgvTasks) {
            if (rgvTask.getTaskStatus() != Rgv60TaskStatus.COMPLETED) {
                return false;
            }
        }

        return true;
    }

    public RgvTaskType getTaskType() {
        return taskType;
    }

    @Override
    public String toString() {
        return "TaskInfo{" +
                "taskId=" + taskId +
                ", rgvTasks=" + rgvTasks +
                '}';
    }
}
